package org.io4j.resource;

import java.io.InputStream;
import java.net.URL;

import org.io4j.data.ByteSource;
import org.io4j.data.TextSource;
import org.io4j.filesystem.File;
import org.io4j.filesystem.Path;

/**
 * An abstract resource descriptor. Every resource can be read from and its
 * contents copied to a file system location.
 */
public interface Resource extends ByteSource, TextSource {

	/**
	 * Returns {@code InputStream} for reading from this resource.
	 * {@code InputStream} has to be closed after use.
	 * 
	 * @throws InputOutputException
	 *            if resource cannot be opened for reading
	 */
	InputStream openInputStream();

	/**
	 * Copies this resource into a destination location determined by the
	 * {@code Path} (destination path) in the file system. If a file denoted by
	 * the destination path already exists in its contents will be replaced.
	 * 
	 * @param destinationPath
	 *           A location in the file system where the resource is to be copied
	 *           to
	 * @return A {@code File} that is a copy of the resource
	 * @throws IllegalArgumentException
	 *            if destination path is {@code null} or denotes an existing
	 *            directory
	 * @throws FileSystemException
	 *            if destination file could not be created
	 * @throws DataTransferException
	 *            if transferring the contents failed
	 */
	File copy(Path destinationPath);

	/**
	 * Returns a URL that this resource resolves to.
	 * 
	 * @throws ResourceResolutionException
	 *            if URL of this resource cannot be resolved
	 */
	URL getUrl();

	/**
	 * Returns the name of this resource.
	 */
	String getName();

	/**
	 * Returns content length of this resource in bytes.
	 * 
	 * @return Number of bytes this resource contains or 0 if the resource
	 *         doesn't exist or other problem occurred while trying to obtain
	 *         content length information.
	 */
	long getContentLength();

	/**
	 * Returns modification timestamp of this resource.
	 * 
	 * @return Number of milliseconds since the epoch (00:00:00 GMT, January 1,
	 *         1970) or 0 if resource doesn't exist or other problem occurred
	 *         while trying to obtain timestamp information.
	 */
	long getModificationTimestamp();
}
